<template>
  <div class="regex-tester-tool">
    <div class="tool-header">
      <h1>正则表达式测试</h1>
      <p>测试和调试正则表达式</p>
    </div>

    <div class="tool-container">
      <el-row :gutter="20">
        <!-- 测试主体 -->
        <el-col :span="16">
          <div class="tester-section">
            <!-- 正则表达式输入 -->
            <div class="regex-input">
              <h3>正则表达式</h3>
              <div class="input-group">
                <el-input
                  v-model="regexPattern"
                  placeholder="请输入正则表达式，如：^[a-zA-Z0-9]+$"
                  size="large"
                  @input="testRegex"
                >
                  <template #prepend>
                    <el-icon><Edit /></el-icon>
                  </template>
                </el-input>
              </div>
              
              <div class="regex-options">
                <div class="options-grid">
                  <div class="option-group">
                    <label>全局匹配：</label>
                    <el-switch v-model="regexFlags.global" @change="testRegex" />
                  </div>
                  <div class="option-group">
                    <label>忽略大小写：</label>
                    <el-switch v-model="regexFlags.ignoreCase" @change="testRegex" />
                  </div>
                  <div class="option-group">
                    <label>多行模式：</label>
                    <el-switch v-model="regexFlags.multiline" @change="testRegex" />
                  </div>
                  <div class="option-group">
                    <label>单行模式：</label>
                    <el-switch v-model="regexFlags.dotAll" @change="testRegex" />
                  </div>
                </div>
              </div>
            </div>
            
            <!-- 测试文本 -->
            <div class="test-text">
              <h3>测试文本</h3>
              <div class="text-actions">
                <el-button @click="pasteText" size="small">
                  <el-icon><DocumentCopy /></el-icon>
                  粘贴文本
                </el-button>
                <el-button @click="clearText" size="small">
                  清空
                </el-button>
                <el-button @click="loadSample" size="small">
                  加载示例
                </el-button>
              </div>
              <el-input
                v-model="testText"
                type="textarea"
                :rows="8"
                placeholder="请输入要测试的文本..."
                @input="testRegex"
                class="text-input"
              />
            </div>
            
            <!-- 测试结果 -->
            <div class="test-result" v-if="testResult">
              <h3>测试结果</h3>
              <div class="result-summary">
                <div class="summary-item">
                  <div class="summary-label">匹配数量</div>
                  <div class="summary-value">{{ testResult.matches.length }}</div>
                </div>
                <div class="summary-item">
                  <div class="summary-label">执行时间</div>
                  <div class="summary-value">{{ testResult.executionTime }}ms</div>
                </div>
                <div class="summary-item">
                  <div class="summary-label">是否匹配</div>
                  <div class="summary-value" :class="testResult.matches.length > 0 ? 'success' : 'danger'">
                    {{ testResult.matches.length > 0 ? '是' : '否' }}
                  </div>
                </div>
              </div>
              
              <div class="matches-list" v-if="testResult.matches.length > 0">
                <h4>匹配结果</h4>
                <div class="match-item" v-for="(match, index) in testResult.matches" :key="index">
                  <div class="match-header">
                    <span class="match-index">匹配 #{{ index + 1 }}</span>
                    <span class="match-position">位置: {{ match.index }}-{{ match.index + match[0].length }}</span>
                  </div>
                  <div class="match-content">
                    <div class="match-text">{{ match[0] }}</div>
                    <div class="match-groups" v-if="match.length > 1">
                      <div class="group-item" v-for="(group, groupIndex) in match.slice(1)" :key="groupIndex">
                        <span class="group-label">组 {{ groupIndex + 1 }}:</span>
                        <span class="group-value">{{ group || '(空)' }}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              
              <div class="highlighted-text" v-if="testResult.matches.length > 0">
                <h4>高亮显示</h4>
                <div class="text-display" v-html="highlightedText"></div>
              </div>
            </div>
            
            <!-- 常用正则 -->
            <div class="common-regex">
              <h3>常用正则表达式</h3>
              <div class="regex-list">
                <div 
                  v-for="regex in commonRegexes" 
                  :key="regex.name"
                  class="regex-item"
                  @click="loadRegex(regex)"
                >
                  <div class="regex-name">{{ regex.name }}</div>
                  <div class="regex-pattern">{{ regex.pattern }}</div>
                  <div class="regex-description">{{ regex.description }}</div>
                </div>
              </div>
            </div>
            
            <!-- 测试历史 -->
            <div class="test-history">
              <h3>测试历史</h3>
              <div class="history-list">
                <div 
                  v-for="(item, index) in testHistory" 
                  :key="index"
                  class="history-item"
                  @click="loadFromHistory(item)"
                >
                  <div class="history-pattern">{{ item.pattern }}</div>
                  <div class="history-info">
                    <span class="history-matches">{{ item.matches }} 个匹配</span>
                    <span class="history-time">{{ item.time }}</span>
                  </div>
                </div>
                <div v-if="testHistory.length === 0" class="empty-history">
                  暂无测试历史
                </div>
              </div>
            </div>
          </div>
        </el-col>

        <!-- 工具和说明 -->
        <el-col :span="8">
          <div class="tools-section">
            <div class="section-header">
              <h3>正则语法</h3>
            </div>
            
            <div class="syntax-help">
              <div class="syntax-group">
                <h4>字符类</h4>
                <div class="syntax-item">
                  <code>.</code> <span>任意字符</span>
                </div>
                <div class="syntax-item">
                  <code>\d</code> <span>数字</span>
                </div>
                <div class="syntax-item">
                  <code>\w</code> <span>字母、数字、下划线</span>
                </div>
                <div class="syntax-item">
                  <code>\s</code> <span>空白字符</span>
                </div>
                <div class="syntax-item">
                  <code>[abc]</code> <span>字符集合</span>
                </div>
                <div class="syntax-item">
                  <code>[^abc]</code> <span>非字符集合</span>
                </div>
              </div>
              
              <div class="syntax-group">
                <h4>量词</h4>
                <div class="syntax-item">
                  <code>*</code> <span>0次或多次</span>
                </div>
                <div class="syntax-item">
                  <code>+</code> <span>1次或多次</span>
                </div>
                <div class="syntax-item">
                  <code>?</code> <span>0次或1次</span>
                </div>
                <div class="syntax-item">
                  <code>{n}</code> <span>恰好n次</span>
                </div>
                <div class="syntax-item">
                  <code>{n,}</code> <span>至少n次</span>
                </div>
                <div class="syntax-item">
                  <code>{n,m}</code> <span>n到m次</span>
                </div>
              </div>
              
              <div class="syntax-group">
                <h4>锚点</h4>
                <div class="syntax-item">
                  <code>^</code> <span>行开始</span>
                </div>
                <div class="syntax-item">
                  <code>$</code> <span>行结束</span>
                </div>
                <div class="syntax-item">
                  <code>\b</code> <span>单词边界</span>
                </div>
              </div>
            </div>
          </div>
          
          <div class="help-section">
            <el-card>
              <template #header>
                <div class="card-header">
                  <span>使用说明</span>
                </div>
              </template>
              
              <div class="help-content">
                <h4>测试步骤：</h4>
                <ol>
                  <li>输入正则表达式</li>
                  <li>选择匹配选项</li>
                  <li>输入测试文本</li>
                  <li>查看匹配结果</li>
                </ol>
                
                <h4>匹配选项：</h4>
                <ul>
                  <li><strong>全局匹配：</strong> 查找所有匹配</li>
                  <li><strong>忽略大小写：</strong> 不区分大小写</li>
                  <li><strong>多行模式：</strong> ^和$匹配行首行尾</li>
                  <li><strong>单行模式：</strong> .匹配换行符</li>
                </ul>
                
                <h4>注意事项：</h4>
                <div class="warning">
                  <p>⚠️ 复杂正则可能影响性能</p>
                  <p>⚠️ 注意转义特殊字符</p>
                  <p>⚠️ 测试前请验证语法</p>
                </div>
              </div>
            </el-card>
          </div>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { Edit, DocumentCopy } from '@element-plus/icons-vue'

const regexPattern = ref('')
const regexFlags = ref({
  global: true,
  ignoreCase: false,
  multiline: false,
  dotAll: false
})
const testText = ref('')
const testResult = ref(null)
const testHistory = ref([])

const commonRegexes = [
  {
    name: '邮箱地址',
    pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
    description: '验证邮箱地址格式'
  },
  {
    name: '手机号码',
    pattern: '^1[3-9]\\d{9}$',
    description: '验证中国大陆手机号'
  },
  {
    name: '身份证号',
    pattern: '^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$',
    description: '验证身份证号码'
  },
  {
    name: 'URL地址',
    pattern: '^https?://[\\w\\-]+(\\.[\\w\\-]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?$',
    description: '验证URL地址'
  },
  {
    name: 'IP地址',
    pattern: '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$',
    description: '验证IPv4地址'
  },
  {
    name: '中文字符',
    pattern: '[\\u4e00-\\u9fa5]',
    description: '匹配中文字符'
  },
  {
    name: '数字',
    pattern: '^\\d+$',
    description: '匹配纯数字'
  },
  {
    name: '字母数字',
    pattern: '^[a-zA-Z0-9]+$',
    description: '匹配字母和数字'
  }
]

const sampleText = `Hello World!
Email: test@example.com
Phone: 13812345678
ID: 110101199001011234
URL: https://www.example.com
IP: 192.168.1.1
中文测试
Number: 12345
Mixed: abc123`

const highlightedText = computed(() => {
  if (!testResult.value || !testResult.value.matches.length) return ''
  
  let text = testText.value
  let offset = 0
  
  testResult.value.matches.forEach((match, index) => {
    const start = match.index + offset
    const end = start + match[0].length
    const highlighted = `<span class="highlight-match">${match[0]}</span>`
    text = text.slice(0, start) + highlighted + text.slice(end)
    offset += highlighted.length - match[0].length
  })
  
  return text.replace(/\n/g, '<br>')
})

const testRegex = () => {
  if (!regexPattern.value.trim() || !testText.value.trim()) {
    testResult.value = null
    return
  }
  
  const startTime = Date.now()
  
  try {
    // 构建正则表达式
    let flags = ''
    if (regexFlags.value.global) flags += 'g'
    if (regexFlags.value.ignoreCase) flags += 'i'
    if (regexFlags.value.multiline) flags += 'm'
    if (regexFlags.value.dotAll) flags += 's'
    
    const regex = new RegExp(regexPattern.value, flags)
    const matches = []
    
    // 执行匹配
    let match
    while ((match = regex.exec(testText.value)) !== null) {
      matches.push(match)
      if (!regexFlags.value.global) break
    }
    
    const executionTime = Date.now() - startTime
    
    testResult.value = {
      matches,
      executionTime
    }
    
    // 添加到历史
    addToHistory()
    
  } catch (error) {
    ElMessage.error('正则表达式语法错误：' + error.message)
    testResult.value = null
  }
}

const pasteText = async () => {
  try {
    const text = await navigator.clipboard.readText()
    testText.value = text
    testRegex()
    ElMessage.success('文本已粘贴')
  } catch (error) {
    ElMessage.error('无法访问剪贴板')
  }
}

const clearText = () => {
  testText.value = ''
  testResult.value = null
  ElMessage.info('文本已清空')
}

const loadSample = () => {
  testText.value = sampleText
  testRegex()
  ElMessage.success('示例文本已加载')
}

const loadRegex = (regex) => {
  regexPattern.value = regex.pattern
  testRegex()
  ElMessage.success(`已加载：${regex.name}`)
}

const addToHistory = () => {
  const historyItem = {
    pattern: regexPattern.value,
    matches: testResult.value?.matches.length || 0,
    time: new Date().toLocaleString('zh-CN')
  }
  
  testHistory.value.unshift(historyItem)
  
  // 限制历史记录数量
  if (testHistory.value.length > 20) {
    testHistory.value = testHistory.value.slice(0, 20)
  }
}

const loadFromHistory = (item) => {
  regexPattern.value = item.pattern
  testRegex()
  ElMessage.success(`已加载：${item.pattern}`)
}
</script>

<style scoped>
.regex-tester-tool {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.tool-header {
  text-align: center;
  margin-bottom: 40px;
}

.tool-header h1 {
  font-size: 2.5rem;
  color: #333;
  margin-bottom: 10px;
}

.tool-header p {
  color: #666;
  font-size: 1.1rem;
}

.tool-container {
  margin-bottom: 40px;
}

.tester-section,
.tools-section {
  background: white;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  border: 1px solid #f0f0f0;
  height: 100%;
}

.regex-input,
.test-text,
.test-result,
.common-regex,
.test-history {
  margin-bottom: 30px;
}

.regex-input h3,
.test-text h3,
.test-result h3,
.common-regex h3,
.test-history h3 {
  color: #333;
  margin-bottom: 20px;
  font-size: 1.3rem;
}

.input-group {
  margin-bottom: 15px;
}

.regex-options {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  border: 1px solid #e9ecef;
}

.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 15px;
}

.option-group {
  display: flex;
  align-items: center;
  gap: 10px;
}

.option-group label {
  font-weight: 500;
  color: #666;
  min-width: 80px;
}

.text-actions {
  display: flex;
  gap: 10px;
  margin-bottom: 15px;
}

.text-input {
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.result-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 15px;
  margin-bottom: 20px;
}

.summary-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  text-align: center;
  border: 1px solid #e9ecef;
}

.summary-label {
  font-size: 0.9rem;
  color: #666;
  margin-bottom: 5px;
}

.summary-value {
  font-size: 1.2rem;
  font-weight: bold;
  color: #333;
}

.summary-value.success {
  color: #28a745;
}

.summary-value.danger {
  color: #dc3545;
}

.matches-list {
  margin-bottom: 20px;
}

.matches-list h4 {
  color: #333;
  margin-bottom: 15px;
  font-size: 1.1rem;
}

.match-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 10px;
  border: 1px solid #e9ecef;
}

.match-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 0.9rem;
}

.match-index {
  color: #667eea;
  font-weight: bold;
}

.match-position {
  color: #666;
}

.match-content {
  font-family: 'Courier New', monospace;
}

.match-text {
  background: #fff3cd;
  padding: 8px;
  border-radius: 4px;
  margin-bottom: 10px;
  border-left: 4px solid #ffc107;
}

.match-groups {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.group-item {
  display: flex;
  gap: 10px;
  font-size: 0.9rem;
}

.group-label {
  color: #666;
  font-weight: 500;
  min-width: 60px;
}

.group-value {
  color: #333;
  font-family: 'Courier New', monospace;
}

.highlighted-text {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 20px;
  border: 1px solid #e9ecef;
}

.highlighted-text h4 {
  color: #333;
  margin-bottom: 15px;
  font-size: 1.1rem;
}

.text-display {
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  background: white;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #e9ecef;
}

.highlight-match {
  background: #fff3cd;
  padding: 2px 4px;
  border-radius: 3px;
  border: 1px solid #ffc107;
  font-weight: bold;
}

.regex-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.regex-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: 1px solid #e9ecef;
}

.regex-item:hover {
  background: #e9ecef;
  transform: translateY(-2px);
}

.regex-name {
  font-size: 1rem;
  font-weight: bold;
  color: #333;
  margin-bottom: 5px;
}

.regex-pattern {
  font-family: 'Courier New', monospace;
  font-size: 0.9rem;
  color: #667eea;
  margin-bottom: 5px;
  word-break: break-all;
}

.regex-description {
  font-size: 0.9rem;
  color: #666;
}

.history-list {
  max-height: 300px;
  overflow-y: auto;
}

.history-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 10px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: 1px solid #e9ecef;
}

.history-item:hover {
  background: #e9ecef;
  transform: translateY(-1px);
}

.history-pattern {
  font-family: 'Courier New', monospace;
  font-size: 1rem;
  color: #333;
  margin-bottom: 8px;
  word-break: break-all;
}

.history-info {
  display: flex;
  gap: 15px;
  font-size: 0.9rem;
  color: #666;
}

.history-matches {
  color: #28a745;
  font-weight: 500;
}

.history-time {
  color: #999;
}

.empty-history {
  text-align: center;
  color: #999;
  padding: 40px 0;
  font-style: italic;
}

.section-header {
  margin-bottom: 20px;
}

.section-header h3 {
  color: #333;
  margin: 0;
  font-size: 1.3rem;
}

.syntax-help {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.syntax-group {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  border: 1px solid #e9ecef;
}

.syntax-group h4 {
  color: #333;
  margin-bottom: 10px;
  font-size: 1.1rem;
}

.syntax-item {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  font-size: 0.9rem;
}

.syntax-item code {
  background: #e9ecef;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: 'Courier New', monospace;
  color: #667eea;
  min-width: 60px;
  text-align: center;
}

.syntax-item span {
  color: #666;
}

.help-section {
  margin-top: 20px;
}

.card-header {
  font-weight: bold;
  color: #333;
}

.help-content h4 {
  color: #333;
  margin: 20px 0 10px 0;
  font-size: 1.1rem;
}

.help-content ol,
.help-content ul {
  color: #666;
  padding-left: 20px;
  margin-bottom: 15px;
}

.help-content li {
  margin-bottom: 5px;
}

.warning {
  background: #fff3cd;
  padding: 15px;
  border-radius: 8px;
  border-left: 4px solid #ffc107;
  margin: 15px 0;
}

.warning p {
  margin: 5px 0;
  color: #856404;
}

@media (max-width: 768px) {
  .tool-header h1 {
    font-size: 2rem;
  }
  
  .options-grid {
    grid-template-columns: 1fr;
  }
  
  .result-summary {
    grid-template-columns: repeat(2, 1fr);
  }
  
  .match-header {
    flex-direction: column;
    gap: 5px;
  }
  
  .history-info {
    flex-direction: column;
    gap: 5px;
  }
}
</style>
